package com.weilele.mvvm.utils.null_option;


import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import kotlin.jvm.functions.Function1;

/**
 * 对于java对象，安全获取数据，类似于kotlin ?. 调用
 *
 * @param <T>
 */
public final class NullOption<T> {
    @Nullable
    private final T value;

    private NullOption(@Nullable T value) {
        this.value = value;
    }

    /**
     * 入口
     *
     * @param input 输入值
     * @param <T>   返回类型
     * @return 返回包装对象
     */
    public static <T> NullOption<T> input(@Nullable T input) {
        return new NullOption<>(input);
    }

    public static <T> NullOption<T> input(@Nullable T input, @Nullable T defaultInput) {
        if (input == null) {
            return new NullOption<>(defaultInput);
        }
        return input(input);
    }

    /**
     * 获取下一个值，输入和返回均可为null
     *
     * @param mapper 转换器
     * @param <U>    下一次结果的返回类型
     * @return 下一次结果的返回包装对象
     */
    public <U> NullOption<U> get(Function1<? super T, ? extends U> mapper) {
        if (value == null) {
            return new NullOption<>(null);
        }
        return new NullOption<>(mapper.invoke(value));
    }

    /**
     * 获取下一个值，如果当前输入值是null，则使用默认的输入对象代替
     *
     * @param mapper 转换器
     * @param input  默认的输入对象
     * @param <U>    下一次结果的返回类型
     * @return 下一次结果的返回包装对象
     */
    public <U> NullOption<U> getOrElseInput(Function1<? super T, ? extends U> mapper, @Nullable T input) {
        if (input == null) {
            return get(mapper);
        }
        if (value == null) {
            return new NullOption<>(mapper.invoke(input));
        }
        return new NullOption<>(mapper.invoke(value));
    }

    /**
     * 获取下一个值，如果当前输入值是null，则下一次的结果返回默认值
     *
     * @param mapper 转换器
     * @param output 下一次返回的默认值
     * @param <U>    下一次结果的返回类型
     * @return 下一次结果的返回包装对象
     */
    public <U> NullOption<U> getOrElseOutput(Function1<? super T, ? extends U> mapper, @Nullable U output) {
        if (output == null) {
            return get(mapper);
        }
        if (value == null) {
            return new NullOption<>(output);
        }
        return new NullOption<>(mapper.invoke(value));
    }

    /**
     * 获取最终结果
     *
     * @return 需要获取的值
     */
    @Nullable
    public T output() {
        return value;
    }

    /**
     * 获取最终结果
     *
     * @param defaultOutput 默认的输出值
     * @return 最后结果
     */
    @NonNull
    public T output(@NonNull T defaultOutput) {
        if (value == null) {
            return defaultOutput;
        }
        return output();
    }
}
